/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once
#include <baja/common.hpp>
#include <journal/views/interfaces.h>
#include <journal/views/scene_state.h>

namespace journal { namespace view {

namespace b = baja;
namespace a = baja::app;

class stack_page_layout : public std::enable_shared_from_this<ipage_layout>, public ipage_layout
{
private:
    stack_page_layout(
        const b::float32 scale,
        const std::shared_ptr<view::inotebook>& notebook
        );

public:
    ~stack_page_layout() {}
    friend class std::_Ref_count_obj<stack_page_layout>;
    static std::shared_ptr<stack_page_layout> create(
        const b::float32 scale,
        const std::shared_ptr<view::inotebook>& notebook
        )
    {
        std::shared_ptr<stack_page_layout> returnValue = std::make_shared<stack_page_layout>(scale, notebook);
        return std::dynamic_pointer_cast<stack_page_layout>(returnValue->shared_from_this());
    }

    // ipage_layout
	void setTransitionProgress(const b::float32 progress);
	void setReference(
        const size_t referencePageNumber, 
        const m::point3d referenceWorld
        );
    void constrainOffsetXY(m::point2d& offsetXY);
    void constrainScale(b::float32& scale);
    void calculatePageSet(
        const std::shared_ptr<icamera>& camera,
        const page_set& currentPageSet,
        size_t currentPage,
        page_set* pageSet, 
        size_t* pageNumber
        );
    m::point3d calculatePagePosition(const size_t pageNumber);
    m::point2d calculateCameraOffsetXY(const size_t pageNumber);
    b::float32 scale() { return _scale; }
    m::point2d focus() { return _focus; }

private:
    void init();
    void cleanup();
    void normalToWorld(const m::point3d& pointNormal, m::point3d* pointWorld);
    void worldToNormal(const m::point3d& pointWorld, m::point3d* pointNormal);
    void pageNumberToNormal(const size_t pageNumber, m::point3d* pointNormal);
    void normalToPageNumber(const m::point3d& pointNormal, size_t* pageNumber);
    void calculateBoundsNormal(m::rectangle* bounds);

private:
    b::float32 _scale;
    m::point2d _focus;
    m::point3d _originWorld;
    m::point4d _boundsNormal;
    std::weak_ptr<view::inotebook> _notebook;
};

inline std::shared_ptr<ipage_layout> createListPageLayout(
    const b::float32 scale,
    const std::shared_ptr<view::inotebook>& notebook
    )
{
    return std::dynamic_pointer_cast<ipage_layout>(stack_page_layout::create(scale, notebook));
}

}} // namespace journal::view